package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmSensitiveDto;
import com.heima.model.wemedia.dtos.WmSensitiveListDto;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.utils.common.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.service.IWmSensitiveService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * <p>
 * 敏感词信息表 服务实现类
 * </p>
 *
 * @author zqc
 * @since 2024-08-21
 */
@Service
public class WmSensitiveServiceImpl extends ServiceImpl<WmSensitiveMapper, WmSensitive> implements IWmSensitiveService {
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 敏感词分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public PageResponseResult listSensitive(WmSensitiveListDto dto) {
        dto.checkParam();
        String sizeString = stringRedisTemplate.opsForValue().get("sensitivesize");
        if (!StringUtils.isEmpty(sizeString)) {
            if (dto.getSize() == Integer.parseInt(sizeString)) {
                HashMap map = redisGetByKey(dto.getPage());
                List<WmSensitive> wmSensitives = (List<WmSensitive>) map.get("Sensitive");
                String total = (String) map.get("total");
                if (!ObjectUtils.isEmpty(wmSensitives) && !StringUtils.isEmpty(total)) {
                    PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), Integer.parseInt(total));
                    result.setData(wmSensitives);
                    return result;
                }
            } else {
                deleteRedis();
            }
        }
        Page<WmSensitive> page = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<WmSensitive> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(!StringUtils.isEmpty(dto.getName()), WmSensitive::getSensitives, dto.getName());
        wrapper.orderByDesc(WmSensitive::getCreatedTime);
        page(page, wrapper);
        PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        result.setData(page.getRecords());

        stringRedisTemplate.opsForValue().set("sensitivetotal", String.valueOf(page.getTotal()));
        stringRedisTemplate.opsForValue().set("sensitivesize", String.valueOf(dto.getSize()));
        for (WmSensitive sensitive : page.getRecords()) {
            stringRedisTemplate.opsForValue().set("sensitive:" + dto.getPage() + ":" + sensitive.getId(),
                    JSON.toJSONString(sensitive));
        }
        return result;
    }

    /**
     * 获取
     *
     * @return
     */
    private HashMap redisGetByKey(Integer page) {
        Set<String> sensitiveKeySet = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keys = new HashSet<>();
            Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().
                    match("sensitive:" + page + ":*").
                    count(1000).
                    build());
            while (cursor.hasNext()) {
                keys.add(new String(cursor.next()));
            }
            return keys;
        });
        List<WmSensitive> wmSensitives = new ArrayList<>();
        for (String sensitiveKey : sensitiveKeySet) {
            String wmSensitiveJson = stringRedisTemplate.opsForValue().get(sensitiveKey);
            WmSensitive wmSensitive = JSON.parseObject(wmSensitiveJson, WmSensitive.class);
            wmSensitives.add(wmSensitive);
        }
        String total = stringRedisTemplate.opsForValue().get("sensitivetotal");
        HashMap<String, Object> map = new HashMap<>();
        map.put("Sensitive", wmSensitives);
        map.put("total", total);
        return map;
    }

    /**
     * 删除
     */
    private void deleteRedis() {
        Set<String> sensitiveKeySet = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keys = new HashSet<>();
            Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match("sensitive*").count(1000).build());
            while (cursor.hasNext()) {
                keys.add(new String(cursor.next()));
            }
            return keys;
        });
        if (ObjectUtils.isEmpty(sensitiveKeySet)) {
            return;
        }
        for (String sensitiveKey : sensitiveKeySet) {
            stringRedisTemplate.delete(sensitiveKey);
        }
        stringRedisTemplate.delete("sensitivesize");
        stringRedisTemplate.delete("sensitivetotal");
    }

    /**
     * 敏感词新增
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveSensitive(WmSensitiveDto dto) {
        if (ObjectUtils.isEmpty(dto)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        LambdaQueryWrapper<WmSensitive> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(!StringUtils.isEmpty(dto.getSensitives()), WmSensitive::getSensitives, dto.getSensitives());
        WmSensitive selectOne = wmSensitiveMapper.selectOne(wrapper);
        if (!ObjectUtils.isEmpty(selectOne)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST);
        }
        WmSensitive wmSensitive = new WmSensitive();
        BeanUtils.copyProperties(dto, wmSensitive);
        wmSensitive.setCreatedTime(new Date());
        wmSensitiveMapper.insert(wmSensitive);
        deleteRedis();
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 修改敏感词
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult updateSensitive(WmSensitiveDto dto) {
        if (ObjectUtils.isEmpty(dto)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        WmSensitive wmSensitive = new WmSensitive();
        BeanUtils.copyProperties(dto, wmSensitive);
        wmSensitive.setCreatedTime(new Date());
        wmSensitiveMapper.updateById(wmSensitive);
        deleteRedis();
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult deleteByid(Integer id) {
        wmSensitiveMapper.deleteById(id);
        deleteRedis();
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
